﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace Groove.Winform.Player
{
    public partial class UcProgress : Control
    {
        private int _maxValue = 1;
        public int MaxValue
        {
            get => _maxValue; 
            set
            {
                if (value < 1) value = 1;
                _maxValue = value;
            }
        }

        private int _value;
        public int Value
        {
            get => _value; 
            set
            {
                if (_isMouseDown) return;
                if (value < 0) value = 0;
                if (value > MaxValue) value = MaxValue;
                _value = value;
                Invalidate();
            }
        }

        public event EventHandler ValueSelected;

        const int LineWeight = 4;
        const int IndicatorSize = 22;
        const int InnerIndicatorSize = 12;
        RectangleF _indicatorRect;
        bool _isMouseDown;

        public UcProgress()
        {
            DoubleBuffered = true;
            SetStyle(ControlStyles.DoubleBuffer | ControlStyles.SupportsTransparentBackColor, true);
            InitializeComponent();
            MouseDown += CCProgress_MouseDown;
            MouseUp += CCProgress_MouseUp;
            MouseMove += CCProgress_MouseMove;
            MouseLeave += CCProgress_MouseLeave;
        }

        private void CCProgress_MouseLeave(object sender, EventArgs e)
        {
            if (!Enabled) return;
            Invalidate();
        }

        private void CCProgress_MouseMove(object sender, MouseEventArgs e)
        {
            if (!Enabled) return;
            if (!_isMouseDown || e.Button != MouseButtons.Left)
            {
                Invalidate();
                return;
            }
            //var mp = PointToClient(MousePosition);
            var newValue = (e.X * 1f / Width) * MaxValue;
            if (newValue < 0) newValue = 0;
            if (newValue > MaxValue) newValue = MaxValue;
            _value = (int)newValue;
            Invalidate();
        }

        private void CCProgress_MouseUp(object sender, MouseEventArgs e)
        {
            if (!Enabled) return;
            if (!_isMouseDown || e.Button != MouseButtons.Left) return;
            _isMouseDown = false;
            ValueSelected?.Invoke(this, EventArgs.Empty);
        }

        private void CCProgress_MouseDown(object sender, MouseEventArgs e)
        {
            if (!Enabled) return;
            if (e.Button != MouseButtons.Left) return;
            var mp = PointToClient(MousePosition);
            if (!_indicatorRect.Contains(mp)) return;
            _isMouseDown = true;
            Invalidate();
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
            var g = pe.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.CompositingQuality = CompositingQuality.HighQuality;

            // Draw baseline
            var lineColor = Enabled ? Color.FromArgb(155, 157, 162) : Color.FromArgb(89, 92, 101);
            using (var brush = new SolidBrush(lineColor))
            {
                var startPoint = Value == 0 ? IndicatorSize : 0;
                var endPoint = Value == MaxValue ? Width - IndicatorSize : Width;
                g.FillRectangle(brush, new Rectangle(startPoint, (Height - LineWeight) / 2, endPoint - startPoint, LineWeight));
            }

            // Calc progress length
            var length = (Width - IndicatorSize) * (Value * 1f / MaxValue);

            // Draw Thumb
            // Outer Cycle
            _indicatorRect = new RectangleF(length, (Height - IndicatorSize) / 2f, IndicatorSize, IndicatorSize);
            using (var brush = new SolidBrush(Color.FromArgb(69, 69, 69)))
            {
                g.FillEllipse(brush, _indicatorRect);
            }
            // Inner Cycle
            var mp = PointToClient(MousePosition);
            var innerIndicatorSize = _indicatorRect.Contains(mp) || _isMouseDown ? InnerIndicatorSize + 2 : InnerIndicatorSize;
            var innerCycleColor = Enabled ? Color.FromArgb(255, 130, 50) : Color.FromArgb(98, 98, 98);
            using (var brush = new SolidBrush(innerCycleColor))
            {
                g.FillEllipse(brush,
                    new RectangleF(_indicatorRect.X + (IndicatorSize - innerIndicatorSize) / 2,
                        _indicatorRect.Y + (IndicatorSize - innerIndicatorSize) / 2, innerIndicatorSize,
                        innerIndicatorSize));
            }

            // Draw progress line
            if (length <= 0) return;
            using (var brush = new SolidBrush(Color.FromArgb(255, 130, 50)))
            {
                g.FillRectangle(brush, new RectangleF(0, (Height - LineWeight) / 2, length, LineWeight));
            }
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnMouseClick(e);
            if (e.Button != MouseButtons.Left) return;
            var persent = e.X * 1f / Width ;
            var value = MaxValue * persent;
            Value = (int)value;
            ValueSelected?.Invoke(this, EventArgs.Empty);
        }        
    }
}
